/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.api.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Equivalence;
import com.yami.shop.api.utils.ApacheHttp;
import com.yami.shop.api.utils.MyUtil;
import com.yami.shop.bean.app.param.PayParam;
import com.yami.shop.bean.model.Mp;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.security.api.model.YamiUser;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.security.common.adapter.DefaultAuthConfigAdapter;
import com.yami.shop.service.MpService;
import com.yami.shop.service.PayService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import com.yami.shop.common.response.ServerResponseEntity;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson.JSONObject;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import com.yami.shop.service.OrderItemService;

/**
 * @author lanhai
 */
@RestController
@RequestMapping("/p/order")
@Tag(name = "订单接口")

public class PayController {
    @Resource
    private  PayService payService;
    @Resource
    private  OrderItemService orderItemService;
    @Resource
    private  MyToken myToken;
    @Resource
    private  MpService mpService;
    private static final Logger logger = LoggerFactory.getLogger(PayController.class);
    @Value("${myapi.jsapi}")
    private String jsapiUrl;
    @Value("${myapi.createorder}")
    private String createorderUrl;
    @Value("${myapi.notify}")
    private String notifyUrl;
    @Value("${myapi.wxserviceip}")
    private String wxserviceip;

    /**
     * getJsapiSign接口
     */
    @PostMapping("/getJsapiSign")
    @Operation(summary = "jsapiSign" , description = "jsapiSign")
    public ServerResponseEntity<JSONObject> getJsapiSign(HttpServletRequest request, @RequestBody PayParam payParam) {
        YamiUser yamiUser = SecurityUtils.getUser();


        if(yamiUser==null){
            throw new YamiShopBindException("请在公众号中点击菜单进入商城");
        }
        if(StrUtil.isBlank(yamiUser.getWxAppId())){
            throw new YamiShopBindException("无法获取微信用户信息，请在公众号中点击菜单进入商城");
        }
        JSONObject jsapiSign=new JSONObject();

        jsapiSign.put("url",payParam.getUrl());
        String sign= ApacheHttp.post(jsapiUrl+yamiUser.getWxAppId()+"/getJsapiSign", JSON.toJSONString(jsapiSign));
        JSONObject jsonSign=JSON.parseObject(sign);


        JSONObject json=new JSONObject();
        json.put("jsapiSign",jsonSign);



        return ServerResponseEntity.success(json);
    }
    /**
     * 支付接口
     */
    @PostMapping("/pay")
    @Operation(summary = "根据订单号进行支付" , description = "根据订单号进行支付")
    public ServerResponseEntity<JSONObject> pay(HttpServletRequest request,HttpSession httpSession, @RequestBody PayParam payParam) {
        YamiUser user = SecurityUtils.getUser();
        String userId = user.getUserId();
        if(StrUtil.isBlank(user.getWxAppId())){
            throw new YamiShopBindException("无法获取微信用户信息，请在公众号中点击菜单进入商城");
        }

        PayInfoDto payInfo = payService.pay(userId, payParam);



        JSONObject jsapiSign=new JSONObject();
        jsapiSign.put("url",payParam.getUrl());
        String sign= ApacheHttp.post(jsapiUrl+user.getWxAppId()+"/getJsapiSign", JSON.toJSONString(jsapiSign));
        JSONObject jsonSign=JSON.parseObject(sign);


        JSONObject param=new JSONObject();
        param.put("appid",user.getWxAppId());
        param.put("attach","attach");
        if(payInfo.getBody().length()>36){
            param.put("body",payInfo.getBody().substring(0,35));
        }else{
            param.put("body",payInfo.getBody());
        }
        param.put("deviceInfo","WEB");
        param.put("feeType", "CNY");
        QueryWrapper<Mp> wrapper = new QueryWrapper<>();
        wrapper.eq("appid" , user.getWxAppId());
        Mp mp =  mpService.getOne(wrapper);
        if(mp==null){
            logger.info("找不到公众号相关参数：mallid="+user.getMallId()+", appid="+user.getWxAppId()  );
            throw new YamiShopBindException("公众号参数没有配置，请联系系统管理员");
        }
        param.put("mchId", mp.getMchid());
        param.put("nonceStr","nonceStr");
        param.put("notifyUrl", notifyUrl+ user.getWxAppId()+"/notify/order");
        String openid=(String)httpSession.getAttribute("openid");
        param.put("openid",openid);
        param.put("outTradeNo",payInfo.getPayNo());
        param.put("receipt", "N");
        param.put("spbillCreateIp", MyUtil.getRemoteIp(request));



        try {
            //是否有余额可以抵扣
            BigDecimal amount = BigDecimal.valueOf(payInfo.getPayAmount());
            Map<String, Object> p = new HashMap<>();
            p.put("pPayNo", payInfo.getPayNo());
            p.put("pAmount", amount);
            orderItemService.CalcPayAmount(p);
            logger.info("==================存储过程返回："+p.toString());
            Integer pret=(Integer)p.get("pret");

            if(pret==null || pret==0){

            }else if(pret==1){
                BigDecimal realAmount=(BigDecimal) p.get("pRealAmount");
                logger.info("realAmount="+realAmount);
                BigDecimal zero=new BigDecimal(0);
                if(realAmount.compareTo(zero)==0){  //全部使用余额支付
                    logger.info("全部使用余额支付："+payInfo.toString());
                    // 根据内部订单号更新order settlement
                    payService.paySuccess(payInfo.getPayNo(), "");
                    try{
                        Map<String,Object> tp=new HashMap<>();
                        tp.put("pPayNo",payInfo.getPayNo());
                        orderItemService.order_add_balance(tp);

                    }catch (Exception e){
                        e.printStackTrace();
                    }
                    JSONObject useBalance=new JSONObject();
                    useBalance.put("allUseBalance",1);
                    return ServerResponseEntity.success(useBalance);
                }
                payInfo.setPayAmount(realAmount.doubleValue());
            }

        }catch (Exception e){
            e.printStackTrace();
        }

        param.put("totalFee", Math.round(payInfo.getPayAmount()*100)  );
        param.put("tradeType", "JSAPI" );
        String url=createorderUrl+user.getWxAppId()+"/createOrder";
        String ret= ApacheHttp.post(url, JSON.toJSONString(param));
        JSONObject json=JSON.parseObject(ret);
        json.put("jsapiSign",jsonSign);

        return ServerResponseEntity.success(json);
    }

    /**
     * 支付通知接口
     */
    @PostMapping("/notifyPay")
    @Operation(summary = "支付通知接口" , description = "支付通知接口,由wxservice模块调用")
    public ServerResponseEntity<Boolean> notifyPay(
            HttpServletRequest request,HttpSession httpSession,@RequestBody Map<String, Object> map


            ) {
        String callIp=MyUtil.getRemoteIp(request);
        logger.info("==========notifyPay call ip: "+callIp);
        if(callIp.equals(wxserviceip)){
            logger.info("========== begin ===========");
            logger.info(map.get("resultCode").toString());
            if("SUCCESS".equals(map.get("resultCode"))){
                logger.info("========== SUCCESS ===========");
                // 根据内部订单号更新order settlement
                payService.paySuccess((String)map.get("outTradeNo"), "");
                try{
                    Map<String,Object> p=new HashMap<>();
                    p.put("pPayNo",(String)map.get("outTradeNo"));
                    orderItemService.order_add_balance(p);


                }catch (Exception e){
                    e.printStackTrace();
                }
                logger.info("========== outTradeNo ==========="+(String)map.get("outTradeNo"));
                return ServerResponseEntity.success();
            }
        }

        return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);



    }






    /**
     * 普通支付接口
     */
    @PostMapping("/normalPay")
    @Operation(summary = "根据订单号进行支付" , description = "根据订单号进行支付")
    public ServerResponseEntity<Boolean> normalPay(@RequestBody PayParam payParam) {
        return ServerResponseEntity.showFailMsg("支付失败，，请在公众号中点击菜单进入商城！");

    }
}
